import { isFunction } from "../utils/utility"
import { effect, track, trigger } from "./effect"

export function computed(getter) {
    let getFunc, setFunc
    if (isFunction(getter)) {
        getFunc = getter
        setFunc = () => {
            console.log("No set function defined")
        }
    }
    else {
        getFunc = getter.get
        setFunc = getter.set
    }

    return new ComputedImpl(getFunc, setFunc)
}

class ComputedImpl {
    constructor(getter, setter) {
        this._setter = setter
        this._value = undefined

        // 脏数据标志
        // 一旦依赖更新，当前的数据就不再准确，设为true
        // 等待下一次调用时计算新值，设为false
        this._dirty = true

        // 不同于reactive，computed不会默认执行，故启用lazy标志
        // 并且需要手动调用更新，故传入调度函数
        this.effect = effect(getter, {
            lazy: true,
            scheduler: () => {
                if (!this._dirty) {
                    this._dirty = true
                    trigger(this, "value")
                }
            }
        })
    }

    get value() {
        if (this._dirty) {
            // 重新计算数值
            this._value = this.effect()
            this._dirty = false
            track(this, "value")
        }
        return this._value
    }

    set value(newValue) {
        this._setter(newValue)
    }
}